package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.core.enums.LendStatusEnum;
import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.*;
import com.atguigu.srb.core.pojo.bo.TransFlowBO;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.pojo.entity.LendItem;
import com.atguigu.srb.core.pojo.entity.UserAccount;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.vo.InvestVO;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.util.LendNoUtils;
import com.atguigu.srb.exception.Assert;
import com.atguigu.srb.result.ResponseEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author fun
 * @since 2021-10-29
 */
@Service
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {
    @Autowired
    LendMapper lendMapper;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    LendService lendService;

    @Autowired
    UserAccountMapper userAccountMapper;

    @Autowired
    TransFlowMapper transFlowMapper;

    @Autowired
    TransFlowService transFlowService;

    @Autowired
    UserInfoService userInfoService;

    @Autowired
    UserAccountService userAccountService;

    @Override
    public String commitInvest(InvestVO investVO) {

        Long investUserId = investVO.getInvestUserId();
        Long lendId = investVO.getLendId();
        Lend lend = lendMapper.selectById(lendId);
        UserInfo userInfo = userInfoMapper.selectById(investUserId);

        //标的状态必须为募资中
        Assert.isTrue(lend.getStatus().intValue()== LendStatusEnum.INVEST_RUN.getStatus().intValue(), ResponseEnum.LEND_INVEST_ERROR);

        //标的不能超卖：(已投金额 + 本次投资金额 )>=标的金额（超卖）
        BigDecimal sum = lend.getInvestAmount().add(new BigDecimal(investVO.getInvestAmount()));
        Assert.isTrue(sum.doubleValue()<=lend.getAmount().doubleValue(),ResponseEnum.LEND_FULL_SCALE_ERROR);

        //账户可用余额充足：当前用户的余额 >= 当前用户的投资金额（可以投资），否则不可投资
        BigDecimal investAccount = userAccountService.getAccount(investUserId);
        Assert.isTrue(investAccount.doubleValue()>=Double.parseDouble(investVO.getInvestAmount()),ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);


        //生成投资信息lendItem
        LendItem lendItem = new LendItem();
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo);
        lendItem.setInvestUserId(investUserId);//投资人id
        lendItem.setInvestName(investVO.getInvestName());//投资人名字
        lendItem.setLendId(investVO.getLendId());//对应的标的id
        lendItem.setInvestAmount(new BigDecimal(investVO.getInvestAmount())); //此笔投资金额
        lendItem.setLendYearRate(lend.getLendYearRate());//年化
        lendItem.setInvestTime(LocalDateTime.now()); //投资时间
        lendItem.setLendStartDate(lend.getLendStartDate()); //开始时间
        lendItem.setLendEndDate(lend.getLendEndDate()); //结束时间

        //预期收益
        BigDecimal expectAmount = lendService.getInterestCount(
                lendItem.getInvestAmount(),
                lendItem.getLendYearRate(),
                new BigDecimal(lend.getPeriod()),
                new BigDecimal(lend.getReturnMethod()));
        lendItem.setExpectAmount(expectAmount);

        //实际收益
        lendItem.setRealAmount(new BigDecimal(0));
        lendItem.setStatus(0);//默认状态：刚刚创建
        baseMapper.insert(lendItem);

        //生成表单
        String formStr = "";
        String investBindCode = userInfo.getBindCode();
        Long benefitUserId = lend.getUserId();
        String benefitBindCode = userInfoService.getBindCodeById(benefitUserId);

        //封装提交至汇付宝的参数
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("voteBindCode", investBindCode);
        paramMap.put("benefitBindCode",benefitBindCode);
        paramMap.put("agentProjectCode", lend.getLendNo());//项目标号
        paramMap.put("agentProjectName", lend.getTitle());

        //在资金托管平台上的投资订单的唯一编号，要和lendItemNo保持一致。
        paramMap.put("agentBillNo", lendItemNo);//订单编号
        paramMap.put("voteAmt", investVO.getInvestAmount());
        paramMap.put("votePrizeAmt", "0");
        paramMap.put("voteFeeAmt", "0");
        paramMap.put("projectAmt", lend.getAmount()); //标的总金额
        paramMap.put("note", "");
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL); //异步通知接口地址
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL); //同步回调url地址
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);
        formStr = FormHelper.buildForm(HfbConst.INVEST_URL, paramMap);
        return formStr;
    }

    @Override
    public void hfbNotify(Map<String, Object> paramMap) {
        String agentBillNo = (String)paramMap.get("agentBillNo");//获取投资编号
        String investBindCode = (String)paramMap.get("voteBindCode");// 投资人的bindCode
        String amount = (String)paramMap.get("voteAmt");// 投资总额

        // 修改投资状态lend_item
        QueryWrapper<LendItem> lendItemQueryWrapper = new QueryWrapper<>();
        lendItemQueryWrapper.eq("lend_item_no",agentBillNo);
        LendItem lendItem = baseMapper.selectOne(lendItemQueryWrapper);
        lendItem.setLendItemNo(agentBillNo);
        lendItem.setStatus(1);
        baseMapper.update(lendItem,lendItemQueryWrapper);

        // 修改标的人数，和已投金额lend
        Long lendId = lendItem.getLendId();
        Lend lend = lendService.getById(lendId);
        Integer investNum = lend.getInvestNum();
        BigDecimal investAmount = lend.getInvestAmount();
        //感觉同一个人多次投资同一个lend时，lend表的investNum不用+1，
        // 在lengItem表中，根据invest_user_id查询是否存在invest_user_id,
        // 存在即lend表的investNum不用+1，否则需要+1
        //但是在查询前就已经插入了一条记录，所以当integer==1时lend表的investNum+1，integer！=1不用+1
        QueryWrapper<LendItem> lendItemQueryWrapper1 = new QueryWrapper<>();
        lendItemQueryWrapper1.eq("invest_user_id",lendItem.getInvestUserId());
        Integer integer = baseMapper.selectCount(lendItemQueryWrapper1);
        if (integer==1) {
            lend.setInvestNum(investNum + 1);
        }
        lend.setInvestAmount(investAmount.add(new BigDecimal(amount)));
        lendService.updateById(lend);

        // 修改投资人账户信息userAccount
        userAccountMapper.updateAccount(investBindCode,new BigDecimal(amount),new BigDecimal("-"+amount));

        // 新增交易流水trans_flow
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBillNo,
                investBindCode,
                new BigDecimal(amount),
                TransTypeEnum.INVEST_LOCK,
                "投标");
        transFlowService.saveTransFlow(transFlowBO);

    }
}
